﻿const { createApp } = Vue;

const TABS = [
  { value: 'dashboard', label: '仪表盘' },
  { value: 'orders', label: '生产订单' },
  { value: 'inventory', label: '现存量' },
  { value: 'reports', label: '报工记录' },
  { value: 'transactions', label: '出入库流水' },
  { value: 'inspections', label: '检验业务' },
  { value: 'apis', label: '接口清单' },
  { value: 'api-logs', label: 'API 日志' },
  { value: 'config', label: '配置管理' }
];

const ORDER_STATUS_OPTIONS = [
  { value: '', label: '全部状态' },
  { value: '待排产', label: '待排产' },
  { value: '生产中', label: '生产中' },
  { value: '暂停', label: '暂停' },
  { value: '已完工', label: '已完工' },
  { value: '已关闭', label: '已关闭' }
];

const MODULE_LABELS = {
  auth: '认证接口',
  production: '生产制造',
  inventory: '库存管理',
  inspection: '检验业务',
  system: '系统服务'
};

const DEFAULT_API_LIST = [
  {
    module: '认证接口',
    method: 'GET',
    path: '/iuap-api-auth/open-auth/selfAppAuth/base/v1/getAccessToken',
    description: '获取认证 Token',
    authRequired: false
  },
  {
    module: '生产制造',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/mfg/productionorder/list',
    description: '生产订单列表查询',
    authRequired: true
  },
  {
    module: '生产制造',
    method: 'GET',
    path: '/iuap-api-gateway/yonbip/mfg/productionorder/detail',
    description: '生产订单详情查询',
    authRequired: true
  },
  {
    module: '检验业务',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/QMS_QIT/checkapply/list',
    description: '检验申请列表查询',
    authRequired: true
  },
  {
    module: '检验业务',
    method: 'GET',
    path: '/iuap-api-gateway/yonbip/QMS_QIT/checkapply/detail',
    description: '检验申请详情查询',
    authRequired: true
  },
  {
    module: '检验业务',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/QMS_QIT/inspectorder/save',
    description: '检验单保存',
    authRequired: true
  },
  {
    module: '库存管理',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/scm/stock/QueryCurrentStocksByCondition',
    description: '现存量查询',
    authRequired: true
  },
  {
    module: '库存管理',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/scm/materialout/mergeSourceData/save',
    description: '材料出库保存',
    authRequired: true
  },
  {
    module: '生产制造',
    method: 'POST',
    path: '/iuap-api-gateway/yonbip/mfg/finishedreport/new/save',
    description: '完工报告保存',
    authRequired: true
  }
];

function createMockOrders() {
  const products = ['高柔电缆', '精密连接器', '伺服驱动器', '注塑模具', '视觉检测套件'];
  const customers = ['华星电子', '华南智造', '星联工业', '恒信科技', '北辰装备'];
  const statuses = [
    { name: '待排产', className: 'status-chip-small warning' },
    { name: '生产中', className: 'status-chip-small' },
    { name: '暂停', className: 'status-chip-small warning' },
    { name: '已完工', className: 'status-chip-small success' },
    { name: '已关闭', className: 'status-chip-small' }
  ];

  return Array.from({ length: 12 }).map((_, index) => {
    const status = statuses[index % statuses.length];
    const planned = 1200 + Math.floor(Math.random() * 800);
    const finished = status.name === '已完工'
      ? planned
      : Math.floor(planned * (0.4 + Math.random() * 0.5));
    const planDate = new Date();
    planDate.setDate(planDate.getDate() + (index + 4));

    return {
      id: `ORD${String(index + 1).padStart(6, '0')}`,
      code: `MO-${planDate.getFullYear()}${String(planDate.getMonth() + 1).padStart(2, '0')}-${String(index + 1).padStart(4, '0')}`,
      product: products[index % products.length],
      specification: `型号-${100 + index}`,
      customer: customers[index % customers.length],
      planned,
      finished,
      statusName: status.name,
      statusClass: status.className,
      planDate: planDate.toISOString()
    };
  });
}

function createMockInventory() {
  const warehouses = ['原材仓', '半成品仓', '成品仓'];
  const statusNameMap = {
    success: '库存充足',
    warning: '库存预警',
    danger: '需要补货'
  };

  return Array.from({ length: 10 }).map((_, index) => {
    const quantity = 800 + Math.floor(Math.random() * 4500);
    const status = quantity < 1200 ? 'danger' : quantity < 2400 ? 'warning' : 'success';

    return {
      id: `INV${index + 1}`,
      materialCode: `MAT-${String(index + 1).padStart(4, '0')}`,
      materialName: `铜芯导线-${index + 1}`,
      specification: `${(index + 1) * 2}mm²`,
      warehouse: warehouses[index % warehouses.length],
      quantity,
      unit: '卷',
      statusClass: `status-chip-small ${status}`,
      statusName: statusNameMap[status]
    };
  });
}

function createMockReports() {
  const workshops = ['总装一线', '精加工线', '装测线'];
  const shifts = ['白班', '夜班'];

  return Array.from({ length: 8 }).map((_, index) => {
    const completed = 300 + Math.floor(Math.random() * 600);
    const qualified = Math.floor(completed * (0.93 + Math.random() * 0.05));
    const reportTime = new Date();
    reportTime.setHours(reportTime.getHours() - (index * 6 + 2));

    return {
      id: `REP${index + 1}`,
      reportCode: `BG-${reportTime.getFullYear()}${String(reportTime.getMonth() + 1).padStart(2, '0')}-${String(index + 1).padStart(3, '0')}`,
      orderCode: `MO-${reportTime.getFullYear()}${String(reportTime.getMonth() + 1).padStart(2, '0')}-${String(index + 3).padStart(4, '0')}`,
      product: `装配工序-${index + 1}`,
      completed,
      qualified,
      reportTime: reportTime.toISOString(),
      workshop: workshops[index % workshops.length],
      shift: shifts[index % shifts.length]
    };
  });
}

function createMockTransactions() {
  const types = [
    { label: '生产领料', negative: true },
    { label: '生产退料', negative: false },
    { label: '采购入库', negative: false },
    { label: '成品入库', negative: false },
    { label: '销售出库', negative: true }
  ];
  const warehouses = ['原材仓', '成品仓', '线束仓'];

  return Array.from({ length: 12 }).map((_, index) => {
    const typeInfo = types[index % types.length];
    const quantity = 50 + Math.floor(Math.random() * 150);
    const actualQty = typeInfo.negative ? quantity * -1 : quantity;
    const occurredAt = new Date();
    occurredAt.setMinutes(occurredAt.getMinutes() - index * 35);

    return {
      id: `TRX${String(index + 1).padStart(5, '0')}`,
      documentCode: `DOC-${String(1000 + index)}`,
      materialCode: `MAT-${String(200 + index)}`,
      type: typeInfo.label,
      quantity: actualQty,
      unit: '件',
      warehouse: warehouses[index % warehouses.length],
      occurredAt: occurredAt.toISOString()
    };
  });
}

function createMockInspections() {
  const processes = ['机加工', '装配', '调试', '成品检验'];
  const inspectors = ['王华', '刘琪', '陈亮', '赵敏'];
  const statuses = [
    { name: '待检', className: 'status-chip-small warning' },
    { name: '检验中', className: 'status-chip-small' },
    { name: '已合格', className: 'status-chip-small success' },
    { name: '复检', className: 'status-chip-small danger' }
  ];

  return Array.from({ length: 10 }).map((_, index) => {
    const status = statuses[index % statuses.length];
    const inspectDate = new Date();
    inspectDate.setDate(inspectDate.getDate() - index);

    return {
      id: `QC${String(index + 1).padStart(4, '0')}`,
      code: `QMS-${inspectDate.getFullYear()}${String(inspectDate.getMonth() + 1).padStart(2, '0')}-${String(index + 1).padStart(3, '0')}`,
      object: `订单 ${String(300 + index)}`,
      process: processes[index % processes.length],
      type: index % 3 === 0 ? '首件检验' : index % 3 === 1 ? '巡检' : '完工检验',
      inspector: inspectors[index % inspectors.length],
      statusName: status.name,
      statusClass: status.className,
      inspectDate: inspectDate.toISOString()
    };
  });
}

function createMockLogs() {
  const templates = [
    { level: 'INFO', message: '系统心跳检测正常' },
    { level: 'INFO', message: '生产订单列表响应 200' },
    { level: 'WARNING', message: '授权令牌将在 5 分钟后过期，已触发刷新' },
    { level: 'ERROR', message: '调用库存接口失败，返回状态码 401' }
  ];
  const now = new Date();

  return Array.from({ length: 18 }).map((_, index) => {
    const template = templates[index % templates.length];
    const lineTime = new Date(now.getTime() - index * 60000);
    const timestamp = lineTime.toISOString().replace('T', ' ').split('.')[0];
    return `${timestamp} [${template.level}] ${template.message}`;
  });
}

function parseErrorMessage(error) {
  if (error && error.response && error.response.data) {
    const data = error.response.data;
    if (typeof data === 'string') {
      return data;
    }
    if (data.message) {
      return data.message;
    }
  }
  if (error && error.message) {
    return error.message;
  }
  return '请求失败，请稍后重试';
}

createApp({
  template: `
    <div class="app-shell">
      <header class="hero">
        <h1>ERP Mock 管理中心</h1>
        <p>模拟用友 YonBIP ERP 数据，为 MES 联调提供可视化支持。</p>
        <div class="status-chip">
          <span class="status-dot" :class="{ online: serverStatus.online }"></span>
          <span>
            {{ serverStatus.online ? '服务已启动' : '服务离线' }} ·
            {{ serverStatus.uptime || '无运行信息' }}
          </span>
        </div>
        <div class="button-row" style="margin-top: 20px;">
          <button class="btn" type="button" @click="refreshAll" :disabled="refreshing">
            {{ refreshing ? '正在刷新...' : '刷新数据' }}
          </button>
          <button class="btn ghost" type="button" @click="fetchLogs" :disabled="logsLoading">
            {{ logsLoading ? '加载日志...' : '刷新日志' }}
          </button>
        </div>
      </header>

      <div class="tab-group">
        <button
          v-for="tab in tabs"
          :key="tab.value"
          class="tab-btn"
          :class="{ active: activeTab === tab.value }"
          type="button"
          @click="activeTab = tab.value"
        >
          {{ tab.label }}
        </button>
      </div>

      <section v-if="activeTab === 'dashboard'" class="view">
        <h2>运行概览</h2>
        <div class="stats-grid">
          <div class="stat-card" v-for="stat in dashboardStats" :key="stat.label">
            <span class="label">{{ stat.label }}</span>
            <span class="value">{{ stat.value }}</span>
          </div>
          <div class="stat-card">
            <span class="label">CPU 使用率</span>
            <span class="value">{{ serverStatus.cpuUsage || '--' }}</span>
          </div>
          <div class="stat-card">
            <span class="label">内存占用</span>
            <span class="value">{{ serverStatus.memoryUsage || '--' }}</span>
          </div>
        </div>
        <h3>最近日志</h3>
        <div class="log-block" style="max-height: 220px;">
          <div v-for="line in recentLogs" :key="line" class="log-line" :class="logClass(line)">
            {{ line }}
          </div>
        </div>
      </section>

      <section v-if="activeTab === 'orders'" class="view">
        <h2>生产订单</h2>
        <div class="filters-row">
          <div class="form-group">
            <label>生产订单号</label>
            <input v-model="filters.orderCode" placeholder="请输入订单号片段" />
          </div>
          <div class="form-group">
            <label>产品名称</label>
            <input v-model="filters.orderProduct" placeholder="请输入产品名称" />
          </div>
          <div class="form-group">
            <label>订单状态</label>
            <select v-model="filters.orderStatus">
              <option v-for="item in orderStatusOptions" :key="item.value" :value="item.value">{{ item.label }}</option>
            </select>
          </div>
        </div>
        <div class="button-row" style="margin-bottom: 18px;">
          <button class="btn secondary" type="button" @click="resetOrderFilters">重置筛选</button>
        </div>
        <table class="sheet" v-if="filteredOrders.length">
          <thead>
            <tr>
              <th>订单编号</th>
              <th>生产单号</th>
              <th>产品名称</th>
              <th>计划数量</th>
              <th>完工数量</th>
              <th>状态</th>
              <th>计划完工</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="order in filteredOrders" :key="order.id">
              <td>{{ order.id }}</td>
              <td>{{ order.code }}</td>
              <td>{{ order.product }}</td>
              <td>{{ formatNumber(order.planned) }}</td>
              <td>{{ formatNumber(order.finished) }}</td>
              <td><span :class="order.statusClass">{{ order.statusName }}</span></td>
              <td>{{ formatDate(order.planDate) }}</td>
              <td><button class="btn secondary" type="button" @click="openOrderJson(order)">JSON</button></td>
            </tr>
          </tbody>
        </table>
        <div v-else class="empty-hint">暂无数据，请稍后重试。</div>
      
        <div class="pager-row" style="display:flex; gap:12px; align-items:center; margin-top:12px;">
          <span>每页条数:</span>
          <select v-model="ordersPagination.pageSize" @change="handleOrdersPageSizeChange">
            <option :value="10">10</option>
            <option :value="12">12</option>
            <option :value="20">20</option>
            <option :value="50">50</option>
            <option :value="100">100</option>
          </select>
          <button class="btn" type="button" @click="changeOrdersPage(-1)" :disabled="ordersPagination.pageIndex <= 1">上一页</button>
          <span>第 {{ ordersPagination.pageIndex }} / {{ ordersPagination.pages }} 页</span>
          <button class="btn" type="button" @click="changeOrdersPage(1)" :disabled="ordersPagination.pageIndex >= ordersPagination.pages">下一页</button>
          <button class="btn secondary" type="button" @click="toggleOrdersRaw">{{ showOrdersRaw ? '隐藏原始结构' : '查看原始标准结构' }}</button>
        </div>
        <div v-if="showOrdersRaw" class="log-block" style="max-height: 280px; margin-top: 12px;">
          <pre class="log-line">{{ JSON.stringify(ordersRaw && ordersRaw.recordList ? ordersRaw.recordList : [], null, 2) }}</pre>
        </div>
      </section>

      <section v-if="activeTab === 'inventory'" class="view">
        <h2>现存量</h2>
        <table class="sheet" v-if="inventory.length">
          <thead>
            <tr>
              <th>物料编码</th>
              <th>物料名称</th>
              <th>规格型号</th>
              <th>仓库</th>
              <th>现存量</th>
              <th>单位</th>
              <th>库存状态</th>
              <th>操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in inventory" :key="item.id">
              <td>{{ item.materialCode }}</td>
              <td>{{ item.materialName }}</td>
              <td>{{ item.specification }}</td>
              <td>{{ item.warehouse }}</td>
              <td>{{ formatNumber(item.quantity) }}</td>
              <td>{{ item.unit }}</td>
              <td><span :class="item.statusClass">{{ item.statusName }}</span></td>
              <td><button class="btn secondary" type="button" @click="openInventoryJson(item)">JSON</button></td>
            </tr>
          </tbody>
        </table>
        <div v-else class="empty-hint">暂无库存数据。</div>
      </section>

      <section v-if="activeTab === 'reports'" class="view">
        <h2>报工记录</h2>
        <table class="sheet" v-if="reports.length">
          <thead>
            <tr>
              <th>报工单号</th>
              <th>生产订单号</th>
              <th>工序/产品</th>
              <th>完工量</th>
              <th>合格量</th>
              <th>报工时间</th>
              <th>班组</th>
              <th>班次</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in reports" :key="item.id">
              <td>{{ item.reportCode }}</td>
              <td>{{ item.orderCode }}</td>
              <td>{{ item.product }}</td>
              <td>{{ formatNumber(item.completed) }}</td>
              <td>{{ formatNumber(item.qualified) }}</td>
              <td>{{ formatDateTime(item.reportTime) }}</td>
              <td>{{ item.workshop }}</td>
              <td>{{ item.shift }}</td>
            </tr>
          </tbody>
        </table>
        <div v-else class="empty-hint">暂无报工数据。</div>
      </section>

      <section v-if="activeTab === 'transactions'" class="view">
        <h2>出入库流水</h2>
        <table class="sheet" v-if="transactions.length">
          <thead>
            <tr>
              <th>发生时间</th>
              <th>单据号</th>
              <th>物料编码</th>
              <th>出入库类型</th>
              <th>数量</th>
              <th>单位</th>
              <th>仓库</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in transactions" :key="item.id">
              <td>{{ formatDateTime(item.occurredAt) }}</td>
              <td>{{ item.documentCode }}</td>
              <td>{{ item.materialCode }}</td>
              <td>{{ item.type }}</td>
              <td :class="{ 'text-danger': item.quantity < 0 }">{{ formatNumber(item.quantity) }}</td>
              <td>{{ item.unit }}</td>
              <td>{{ item.warehouse }}</td>
            </tr>
          </tbody>
        </table>
        <div v-else class="empty-hint">暂无出入库流水。</div>
      </section>

      <section v-if="activeTab === 'inspections'" class="view">
        <h2>检验业务</h2>
        <table class="sheet" v-if="inspections.length">
          <thead>
            <tr>
              <th>检验单号</th>
              <th>检验对象</th>
              <th>工序</th>
              <th>检验类型</th>
              <th>检验员</th>
              <th>状态</th>
              <th>检验日期</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="item in inspections" :key="item.id">
              <td>{{ item.code }}</td>
              <td>{{ item.object }}</td>
              <td>{{ item.process }}</td>
              <td>{{ item.type }}</td>
              <td>{{ item.inspector }}</td>
              <td><span :class="item.statusClass">{{ item.statusName }}</span></td>
              <td>{{ formatDate(item.inspectDate) }}</td>
            </tr>
          </tbody>
        </table>
        <div v-else class="empty-hint">暂无检验业务数据。</div>
      </section>

      <section v-if="activeTab === 'apis'" class="view">
        <h2>开放接口清单</h2>
        <div v-if="apisByModule.length">
          <div v-for="group in apisByModule" :key="group.module" style="margin-bottom: 26px;">
            <h3>{{ group.module }}</h3>
            <table class="sheet">
              <thead>
                <tr>
                  <th>请求方式</th>
                  <th>接口路径</th>
                  <th>说明</th>
                  <th>鉴权</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="item in group.items" :key="item.path + item.method">
                  <td>{{ item.method }}</td>
                  <td>{{ item.path }}</td>
                  <td>{{ item.description }}</td>
                  <td>
                    <span class="status-chip-small" :class="item.authRequired ? 'warning' : 'success'">
                      {{ item.authRequired ? '需要 Token' : '无需 Token' }}
                    </span>
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        <div v-else class="empty-hint">暂无接口信息。</div>
      </section>

      <section v-if="activeTab === 'api-logs'" class="view">
        <h2>API 访问日志</h2>
        <div class="log-block">
          <div v-for="line in apiLogs" :key="line" class="log-line" :class="logClass(line)">
            {{ line }}
          </div>
        </div>
      </section>

      <section v-if="activeTab === 'config'" class="view">
        <h2>系统配置</h2>
        <div class="config-grid">
          <div class="form-group">
            <label>APP_KEY</label>
            <input v-model="systemConfig.app_key" placeholder="请输入 APP_KEY" />
            <span class="form-helper">默认值来自用友开放平台配置</span>
          </div>
          <div class="form-group">
            <label>APP_SECRET</label>
            <input v-model="systemConfig.app_secret" placeholder="请输入 APP_SECRET" />
          </div>
          <div class="form-group">
            <label>APP_NAME</label>
            <input v-model="systemConfig.app_name" placeholder="请输入应用名称" />
          </div>
          <div class="form-group">
            <label>TENANT_ID</label>
            <input v-model="systemConfig.tenant_id" placeholder="请输入租户标识" />
            <span class="form-helper">若为空，默认使用当前租户配置</span>
          </div>
          <div class="form-group">
            <label>Token 过期秒数</label>
            <input v-model.number="systemConfig.token_expire_seconds" type="number" min="60" step="60" />
          </div>
          <div class="form-group">
            <label>运行环境</label>
            <input v-model="systemConfig.system_environment" placeholder="如：测试环境" />
          </div>
          <div class="form-group">
            <label>服务地址</label>
            <input :value="serviceAddress" disabled />
            <span class="form-helper">来自当前运行配置，实时更新</span>
          </div>
        </div>
        <div class="button-row" style="margin-top: 24px;">
          <button class="btn" type="button" @click="saveSystemConfig" :disabled="savingConfig">
            {{ savingConfig ? '保存中...' : '保存配置' }}
          </button>
          <button class="btn secondary" type="button" @click="fetchSystemConfig" :disabled="savingConfig">
            重新加载
          </button>
        </div>
        <div v-if="configFeedback" class="feedback" :class="configFeedback.type">
          {{ configFeedback.message }}
        </div>
        <pre class="code-box">curl -G "{{ baseUrl }}/iuap-api-auth/open-auth/selfAppAuth/base/v1/getAccessToken" \
  --data-urlencode "appKey={{ systemConfig.app_key || '<APP_KEY>' }}" \
  --data-urlencode "timestamp=$(date +%s%3N)" \
  --data-urlencode "signature=<已按规则计算的签名>"
</pre>
      </section>
    </div>

    <!-- 全局唯一 JSON 模态框 -->
    <div v-if="jsonModal.visible" class="modal-mask" style="position:fixed;left:0;top:0;right:0;bottom:0;background:rgba(0,0,0,0.35);display:flex;align-items:center;justify-content:center;z-index:9999;">
      <div class="modal" style="background:#fff;border-radius:8px;min-width:60vw;max-width:80vw;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 8px 24px rgba(0,0,0,0.2);">
        <div style="display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #eee;">
          <div>
            <strong>{{ jsonModal.title }}</strong>
          </div>
          <div>
            <button class="btn" type="button" @click="closeJsonModal" style="margin-left:6px;">关闭</button>
          </div>
        </div>
        <div style="padding:12px;overflow:auto;">
          <pre style="margin:0;white-space:pre-wrap;word-break:break-all;">{{ jsonModal.pretty }}</pre>
        </div>
      </div>
    </div>
  `,
  data() {
    return {
      tabs: TABS,
      activeTab: 'dashboard',
      refreshing: false,
      logsLoading: false,
      savingConfig: false,
      serverStatus: {
        online: false,
        uptime: '--',
        cpuUsage: '--',
        memoryUsage: '--',
        updatedAt: null
      },
      apiList: DEFAULT_API_LIST,
      orders: createMockOrders(),
      ordersTotal: 0,
      ordersRaw: null,
      ordersPagination: { pageIndex: 1, pageSize: 12, pages: 1 },
      showOrdersRaw: false,
      jsonModal: { visible: false, title: "", pretty: "", records: [], index: 0, total: 0 },
      inventory: createMockInventory(),
      inventoryRaw: [],
      reports: createMockReports(),
      transactions: createMockTransactions(),
      inspections: createMockInspections(),
      apiLogs: createMockLogs(),
      filters: {
        orderCode: '',
        orderStatus: '',
        orderProduct: ''
      },
      systemConfig: {
        app_key: '',
        app_secret: '',
        app_name: '',
        tenant_id: '',
        token_expire_seconds: 7200,
        system_environment: ''
      },
      systemMeta: {
        host: '',
        port: '',
        system_name: '',
        system_version: ''
      },
      configFeedback: null
    };
  },
  computed: {
    dashboardStats() {
      return [
        { label: '接口数量', value: this.apiList.length },
        { label: '生产订单', value: this.ordersTotal || this.orders.length },
        { label: '库存品项', value: this.inventory.length },
        { label: '日志条数', value: this.apiLogs.length }
      ];
    },
    orderStatusOptions() {
      return ORDER_STATUS_OPTIONS;
    },
    filteredOrders() {
      return this.orders.filter(order => {
        const matchCode = this.filters.orderCode
          ? order.code.toLowerCase().includes(this.filters.orderCode.trim().toLowerCase())
          : true;
        const matchProduct = this.filters.orderProduct
          ? order.product.includes(this.filters.orderProduct.trim())
          : true;
        const matchStatus = this.filters.orderStatus
          ? order.statusName === this.filters.orderStatus
          : true;
        return matchCode && matchProduct && matchStatus;
      });
    },
    apisByModule() {
      const grouped = new Map();
      this.apiList.forEach(item => {
        const moduleName = MODULE_LABELS[item.module] || item.module || '其他';
        if (!grouped.has(moduleName)) {
          grouped.set(moduleName, []);
        }
        grouped.get(moduleName).push(item);
      });
      return Array.from(grouped.entries()).map(([module, items]) => ({ module, items }));
    },
    recentLogs() {
      return this.apiLogs.slice(0, 8);
    },
    baseUrl() {
      return `${window.location.protocol}//${window.location.host}`;
    },
    serviceAddress() {
      if (this.systemMeta.host || this.systemMeta.port) {
        return `${this.systemMeta.host || '0.0.0.0'}:${this.systemMeta.port || ''}`;
      }
      return `${window.location.hostname}:${window.location.port}`;
    }
  },
  methods: {
    formatNumber(value) {
      if (value === null || value === undefined || Number.isNaN(Number(value))) {
        return '-';
      }
      return Number(value).toLocaleString('zh-CN');
    },
    formatDate(isoString) {
      if (!isoString) return '-';
      const date = new Date(isoString);
      if (Number.isNaN(date.getTime())) return '-';
      return date.toLocaleDateString('zh-CN');
    },
    formatDateTime(isoString) {
      if (!isoString) return '-';
      const date = new Date(isoString);
      if (Number.isNaN(date.getTime())) return '-';
      return date.toLocaleString('zh-CN', { hour12: false });
    },
    logClass(line) {
      if (!line) return '';
      if (line.includes('[ERROR]')) return 'error';
      if (line.includes('[WARNING]') || line.includes('[WARN]')) return 'warn';
      return '';
    },
    resetOrderFilters() {
      this.filters = {
        orderCode: '',
        orderStatus: '',
        orderProduct: ''
      };
    },
    async refreshAll() {
      try {
        this.refreshing = true;
        await Promise.all([
          this.fetchServerStatus(),
          this.fetchApiList(),
          this.fetchLogs(),
          this.fetchSystemConfig(),
          this.fetchOrders(),
          this.fetchInventory(),
          this.fetchReports(),
          this.fetchTransactions(),
          this.fetchInspections()
        ]);
      } finally {
        this.refreshing = false;
      }
    },
    async fetchServerStatus() {
      try {
        const { data } = await axios.get('/api/status');
        if (data && data.data) {
          const status = data.data;
          this.serverStatus = {
            online: (status.status || '').toLowerCase() === 'running' || status.status === 'online',
            uptime: status.uptime || '--',
            cpuUsage: status.cpu_usage || status.cpuUsage || '--',
            memoryUsage: status.memory_usage || status.memoryUsage || '--',
            updatedAt: new Date().toISOString()
          };
        }
      } catch (error) {
        console.error('获取服务状态失败', error);
        this.serverStatus.online = false;
      }
    },
    async fetchApiList() {
      try {
        const { data } = await axios.get('/api/config');
        if (data && Array.isArray(data.data)) {
          this.apiList = data.data.map(item => {
            const moduleLabel = item.module_label || MODULE_LABELS[item.module] || item.module || '其他';
            return {
              module: moduleLabel,
              moduleKey: item.module,
              method: item.method || 'GET',
              path: item.path,
              description: item.description || '',
              authRequired: Boolean(item.auth_required)
            };
          });
        } else {
          this.apiList = DEFAULT_API_LIST;
        }
      } catch (error) {
        console.error('获取接口配置失败', error);
        this.apiList = DEFAULT_API_LIST;
      }
    },
    async fetchOrders() {
      try {
        const params = { pageIndex: this.ordersPagination.pageIndex, pageSize: this.ordersPagination.pageSize };
        const { data } = await axios.get('/api/dashboard/orders', { params });
        if (data && data.data) {
          if (Array.isArray(data.data.items)) {
            const recs = (data.data.raw && data.data.raw.recordList) ? data.data.raw.recordList : [];
            this.orders = data.data.items.map((item, idx) => ({
              id: item.id || item.code,
              code: item.code,
              product: item.product,
              specification: item.specification,
              planned: item.planned,
              finished: item.finished,
              statusName: item.status_name || '在制',
              statusClass: this.mapOrderStatusClass(item.status_name),
              planDate: item.plan_date,
              _raw: recs[idx] || null
            }));
          }
          this.ordersRaw = data.data.raw || null;
          if (this.ordersRaw) {
            const total = Number(this.ordersRaw.recordCount) || 0;
            this.ordersTotal = total;
            this.ordersPagination.pages = Number(this.ordersRaw.pageCount) || Math.max(1, Math.ceil(total / this.ordersPagination.pageSize));
          }
        }
      } catch (error) {
        console.error('获取生产订单失败', error);
      }
    },
    async fetchInventory() {
      try {
        const { data } = await axios.get('/api/dashboard/inventory');
        if (data && data.data && Array.isArray(data.data.items)) {
          const statusNameMap = {
            success: '库存充足',
            warning: '库存预警',
            danger: '需要补货'
          };
          const recs = (data.data.raw && data.data.raw.records) ? data.data.raw.records : [];
          this.inventory = data.data.items.map((item, idx) => {
            const quantity = Number(item.quantity) || 0;
            const statusClass = quantity < 1200 ? 'danger' : quantity < 2400 ? 'warning' : 'success';
            return {
              id: item.id || item.materialCode,
              materialCode: item.materialCode,
              materialName: item.materialName,
              specification: item.specification || '-',
              warehouse: item.warehouse || '-',
              quantity,
              unit: item.unit || '',
              statusClass: `status-chip-small ${statusClass}`,
              statusName: statusNameMap[statusClass],
              _raw: recs[idx] || null
            };
          });
          this.inventoryRaw = (data.data.raw && data.data.raw.records) ? data.data.raw.records : [];
        }
      } catch (error) {
        console.error('获取库存数据失败', error);
      }
    },
    async fetchReports() {
      try {
        const { data } = await axios.get('/api/dashboard/reports');
        if (data && data.data && Array.isArray(data.data.reports)) {
          this.reports = data.data.reports.map(item => ({
            id: item.report_id || item.reportCode,
            reportCode: item.report_code || item.reportCode,
            orderCode: item.order_code,
            product: item.product_name || item.product,
            completed: item.completed_quantity || item.completed,
            qualified: item.qualified_quantity || item.qualified,
            reportTime: item.submit_time || item.reportTime,
            workshop: item.workshop || '-',
            shift: item.shift || '-'
          }));
        }
      } catch (error) {
        console.error('获取报工数据失败', error);
      }
    },
    async fetchTransactions() {
      try {
        const { data } = await axios.get('/api/dashboard/transactions');
        if (data && data.data && Array.isArray(data.data.transactions)) {
          this.transactions = data.data.transactions.map(item => ({
            id: item.transaction_id || item.transaction_code,
            documentCode: item.transaction_code || item.reference_doc,
            materialCode: item.material_code,
            type: item.transaction_type_name || item.transaction_type,
            quantity: item.quantity,
            unit: item.unit,
            warehouse: item.warehouse_name,
            occurredAt: item.transaction_time
          }));
        }
      } catch (error) {
        console.error('获取出入库流水失败', error);
      }
    },
    async fetchInspections() {
      try {
        const { data } = await axios.get('/api/dashboard/inspections');
        if (data && data.data && Array.isArray(data.data.records)) {
          this.inspections = data.data.records.map(item => ({
            id: item.id || item.apply_code,
            code: item.code || item.apply_code,
            object: item.object_name || item.product_name || '-',
            process: item.process_name || item.work_procedure || '-',
            type: item.check_type_name || item.check_type || '-',
            inspector: item.inspector || item.inspector_name || '-',
            statusName: item.status_name || item.statusName || '待检',
            statusClass: this.mapInspectionStatusClass(item.status_name || item.statusName),
            inspectDate: item.inspect_date || item.apply_date
          }));
        }
      } catch (error) {
        console.error('获取检验业务失败', error);
      }
    },
    async fetchLogs() {
      try {
        this.logsLoading = true;
        const { data } = await axios.get('/api/logs', { params: { lines: 120 } });
        if (data && data.data && Array.isArray(data.data.logs)) {
          this.apiLogs = data.data.logs.reverse();
        }
      } catch (error) {
        console.error('获取日志失败', error);
      } finally {
        this.logsLoading = false;
      }
    },
    async fetchSystemConfig() {
      try {
        const { data } = await axios.get('/api/system/config');
        if (data && data.data) {
          const payload = data.data;
          this.systemConfig = {
            app_key: payload.app_key || '',
            app_secret: payload.app_secret || '',
            app_name: payload.app_name || '',
            tenant_id: payload.tenant_id || '',
            token_expire_seconds: payload.token_expire_seconds || 7200,
            system_environment: payload.system_environment || ''
          };
          this.systemMeta = {
            host: payload.host || '',
            port: payload.port || '',
            system_name: payload.system_name || '',
            system_version: payload.system_version || ''
          };
        }
        this.configFeedback = null;
      } catch (error) {
        console.error('加载系统配置失败', error);
        this.configFeedback = {
          type: 'error',
          message: parseErrorMessage(error)
        };
      }
    },
    mapOrderStatusClass(statusName) {
      switch (statusName) {
        case '待排产':
          return 'status-chip-small warning';
        case '已完工':
          return 'status-chip-small success';
        case '暂停':
          return 'status-chip-small danger';
        case '已关闭':
          return 'status-chip-small';
        default:
          return 'status-chip-small';
      }
    },
    mapInspectionStatusClass(statusName) {
      switch (statusName) {
        case '已合格':
          return 'status-chip-small success';
        case '检验中':
          return 'status-chip-small';
        case '复检':
          return 'status-chip-small warning';
        default:
          return 'status-chip-small warning';
      }
    },
    async saveSystemConfig() {
      try {
        this.savingConfig = true;
        this.configFeedback = null;
        const payload = {
          app_key: (this.systemConfig.app_key || '').trim(),
          app_secret: (this.systemConfig.app_secret || '').trim(),
          app_name: (this.systemConfig.app_name || '').trim(),
          tenant_id: (this.systemConfig.tenant_id || '').trim(),
          token_expire_seconds: Number(this.systemConfig.token_expire_seconds) || 7200,
          system_environment: (this.systemConfig.system_environment || '').trim()
        };
        const { data } = await axios.post('/api/system/config', payload);
        await this.fetchSystemConfig();
        this.configFeedback = {
          type: 'success',
          message: (data && data.message) ? data.message : '配置已保存并立即生效'
        };
      } catch (error) {
        console.error('保存配置失败', error);
        this.configFeedback = {
          type: 'error',
          message: parseErrorMessage(error)
        };
      } finally {
        this.savingConfig = false;
      }
    },
    toggleOrdersRaw() {
      this.showOrdersRaw = !this.showOrdersRaw;
    },
    changeOrdersPage(dir) {
      const newPage = this.ordersPagination.pageIndex + dir;
      if (newPage >= 1 && newPage <= this.ordersPagination.pages) {
        this.ordersPagination.pageIndex = newPage;
        this.fetchOrders();
      }
    },
    handleOrdersPageSizeChange() {
      this.ordersPagination.pageIndex = 1;
      this.fetchOrders();
    },
    openOrderJson(order) {
      const payload = (order && order._raw) ? order._raw : order;
      this.jsonModal.title = 'Order JSON - ' + (order && order.code ? order.code : '');
      try { this.jsonModal.pretty = JSON.stringify(payload, null, 2); } catch (e) { this.jsonModal.pretty = String(payload); }
      this.jsonModal.visible = true;
    },
    closeJsonModal() {
      this.jsonModal.visible = false;
    },
    openInventoryJson(item) {
      const payload = (item && item._raw) ? item._raw : item;
      this.jsonModal.title = 'Inventory JSON - ' + (item && item.materialCode ? item.materialCode : '');
      try { this.jsonModal.pretty = JSON.stringify(payload, null, 2); } catch (e) { this.jsonModal.pretty = String(payload); }
      this.jsonModal.visible = true;
    }
  },
  mounted() {
    this.refreshAll();
  }
}).mount('#app');